package com.dd.cloud.user.service.role.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dd.cloud.user.entity.role.AdminRole;
import com.dd.cloud.user.entity.role.RoleMenu;
import com.dd.cloud.user.entity.role.RoleToMenu;
import com.dd.cloud.user.entity.role.UserToRole;

import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.mapper.role.AdminRoleMapper;
import com.dd.cloud.user.mapper.role.RoleMenuMapper;
import com.dd.cloud.user.mapper.role.RoleToMenuMapper;
import com.dd.cloud.user.mapper.role.UserToRoleMapper;
import com.dd.cloud.user.req.role.*;
import com.dd.cloud.user.service.role.IAdminPowerService;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zk
 */
@Slf4j
@Service
public class AdminPowerServiceImpl implements IAdminPowerService {
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Autowired
    private AdminRoleMapper adminRoleMapper;
    @Autowired
    private RoleToMenuMapper roleToMenuMapper;
    @Autowired
    private UserToRoleMapper userToRoleMapper;

    /**
     * 查询树形菜单
     *
     * @param flag
     * @return
     */
    @Override
    public List<RoleMenu> queryMenuTree(Integer flag) {
        if (flag == null) {
            flag = LoginInfo.UserType.ADMIN;
        }
        List<RoleMenu> list = getRoleMenuByType(flag);
        return toMenuTree(list);
    }

    /**
     * 将list转换树形菜单
     *
     * @param list
     * @return
     */
    public List<RoleMenu> toMenuTree(List<RoleMenu> list) {
        List<RoleMenu> parents = list.stream().filter(item -> item.getPid().equals(0)).collect(Collectors.toList());
        List<RoleMenu> sons = list.stream().filter(item -> !item.getPid().equals(0)).collect(Collectors.toList());
        //集合排序 正序
        parents.sort(Comparator.comparingInt(t -> t.getSort().intValue()));
        parents.forEach(item -> forRoleMenu(item, sons));
        return parents;
    }

    /**
     * 递归下挂菜单
     *
     * @param parent
     * @param sons
     */
    public void forRoleMenu(RoleMenu parent, List<RoleMenu> sons) {
        List<RoleMenu> list = sons.stream()
                .filter(item -> item.getPid().equals(parent.getId()))
                .sorted(Comparator.comparingInt(t -> t.getSort().intValue()))
                .collect(Collectors.toList());
        //集合排序 正序
        list.forEach(item -> {
                    if (parent.getSonMenus() == null) {
                        parent.setSonMenus(new ArrayList<>());
                    }
                    parent.getSonMenus().add(item);
                    forRoleMenu(item, sons);
                }
        );
    }

    /**
     * 查询所有菜单 通过场景
     *
     * @param flag
     * @return
     */
    @Override
    public List<RoleMenu> getRoleMenuByType(Integer flag) {
        List<RoleMenu> list = roleMenuMapper.getRoleMenuByType(flag);
        return list;
    }

    /**
     * 查询菜单通过菜单编号
     *
     * @param id
     * @return
     */
    @Override
    public RoleMenu queryMenuById(Integer id) {
        return roleMenuMapper.selectById(id);
    }

    /**
     * 修改菜单
     *
     * @param rm
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleMenu(RoleMenuUpdateReq rm) {
        RoleMenu roleMenu = roleMenuMapper.selectById(rm.getId());
        if (roleMenu == null) {
            throw new ZekeException(400, "菜单不存在");
        }
        BeanUtils.copyProperties(rm, roleMenu);
        roleMenuMapper.updateById(roleMenu);
    }

    /**
     * 添加菜单
     *
     * @param rm
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRoleMenu(RoleMenuAddReq rm) {
        RoleMenu roleMenu = new RoleMenu();
        BeanUtils.copyProperties(rm, roleMenu);
        roleMenu.setStatus(1);
        roleMenuMapper.insert(roleMenu);
    }

    /**
     * 添加系统管理员角色
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AdminRole addAdminRole(RoleCreateReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        if (req.getType() == null) {
            req.setType(LoginInfo.UserType.ADMIN);
        }
        QueryWrapper<AdminRole> qw = new QueryWrapper<>();
        qw.lambda().eq(AdminRole::getType, req.getType());
        qw.lambda().eq(AdminRole::getRoleName, req.getRoleName());
        qw.lambda().ne(AdminRole::getStatus, -1);
        if (loginInfo.getType() == LoginInfo.UserType.PHAR) {
            qw.lambda().eq(AdminRole::getPharId, loginInfo.getPharId());
        }
        int count = adminRoleMapper.selectCount(qw);
        if (count > 0) {
            throw new ZekeException(400, "角色名称已存在!");
        }
        AdminRole ar = new AdminRole();
        BeanUtils.copyProperties(req, ar);
        if (req.getAdmin() != null) {
            ar.setAdmin(req.getAdmin());
        } else {
            ar.setAdmin(2);
        }
        ar.setCreateDate(LocalDateTime.now());
        if (loginInfo.getType() == LoginInfo.UserType.PHAR) {
            ar.setPharId(loginInfo.getPharId());
        }
        int num = adminRoleMapper.insert(ar);
        if (num < 0) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
        if (req.getMenuIds() != null && req.getMenuIds().size() > 0) {
            num = roleToMenuMapper.addBatchRoleToMenu(ar.getId(), req.getMenuIds());
            if (num < 0) {
                throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
            }
        }
        return ar;
    }

    /**
     * 修改角色
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAdminRole(RoleUpdateReq req) {
        if (req.getFlag() == 1) {
            if (req.getType() == null) {
                req.setType(LoginInfo.UserType.ADMIN);
            }
            LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
            QueryWrapper<AdminRole> qw = new QueryWrapper<>();
            qw.lambda().eq(AdminRole::getType, req.getType());
            qw.lambda().eq(AdminRole::getRoleName, req.getRoleName());
            qw.lambda().ne(AdminRole::getId, req.getId());
            qw.lambda().ne(AdminRole::getStatus, -1);
            if (loginInfo.getType() == LoginInfo.UserType.PHAR) {
                qw.lambda().eq(AdminRole::getPharId, loginInfo.getPharId());
            }
            int count = adminRoleMapper.selectCount(qw);
            if (count > 0) {
                throw new ZekeException(400, "角色名称已存在!");
            }
            AdminRole adminRole = adminRoleMapper.selectById(req.getId());
            if (adminRole.getAdmin() == 1) {
                throw new ZekeException(400, "无法操作超级管理员角色");
            }
            if (adminRole.getStatus() == -1) {
                throw new ZekeException(400, "删除角色无法操作");
            }
            AdminRole ar = new AdminRole();
            ar.setId(req.getId());
            ar.setRoleName(req.getRoleName());
            ar.setRoleDesc(req.getRoleDesc());
            ar.setAdmin(2);
            ar.setStatus(req.getStatus());
            int num = adminRoleMapper.updateById(ar);
            if (num < 1) {
                throw new ZekeException(400, "角色修改失败!");
            }
            //修改角色权限
            ar.setMenuIds(req.getMenuIds());
            updateRolePower(ar);
        } else if (req.getFlag() == 2) {
            AdminRole ar = new AdminRole();
            ar.setId(req.getId());
            ar.setStatus(req.getStatus());
            int num = adminRoleMapper.updateById(ar);
            if (num < 1) {
                throw new ZekeException(400, "角色修改失败!");
            }
        }
    }

    /**
     * 查询角色的菜单
     *
     * @param roleId
     * @return
     */
    @Override
    public List<RoleMenu> queryRoleMenuByRoleId(Integer roleId) {
        return roleMenuMapper.getRoleMenuByRoleId(roleId);
    }

    /**
     * 查询系统管理员拥有的菜单
     *
     * @param userId
     * @return
     */
    @Override
    public List<RoleMenu> queryUserMenus(Integer flag, Integer userId) {
        List<RoleMenu> list;
        Integer admin = queryRoleIsAdmin(userId, flag);
        if (admin.equals(1)) {
            list = roleMenuMapper.getUserMenuByType(flag);
        } else {
            list = roleMenuMapper.getUserMenuByUserId(flag, userId);
        }
        return toMenuTree(list);
    }

    /**
     * 查询管理员权限
     *
     * @param userId
     * @param url
     * @return
     */
    @Override
    public Integer queryRoleMenu(Integer userId, String url) {
        return roleMenuMapper.getRoleMenuByRoleIdAndUrl(userId, url);
    }

    /**
     * 查询机构管理员所有角色
     *
     * @return
     */
    @Override
    public List<AdminRole> queryAdminRoleListAll() {
        QueryWrapper<AdminRole> qw = new QueryWrapper<>();
        qw.lambda().eq(AdminRole::getStatus, 1);
        return adminRoleMapper.selectList(qw);
    }

    /**
     * 查询机构的所有角色
     *
     * @return
     */
    @Override
    public IPage<AdminRole> queryAdminRoleList(RoleQueryTermsReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        req.setOrder(req.getOrder() == null ? "desc" : req.getOrder());
        IPage<AdminRole> iPage = req.pagePojo();
        QueryWrapper<AdminRole> qw = new QueryWrapper<>();
        if (loginInfo.getType() == LoginInfo.UserType.PHAR) {
            qw.lambda().eq(AdminRole::getPharId, loginInfo.getPharId());
        }
        qw.lambda().eq(AdminRole::getType, req.getFlag());
        if (req.getStatus() == null) {
            qw.lambda().ne(AdminRole::getStatus, -1);
        } else {
            qw.lambda().eq(AdminRole::getStatus, req.getStatus());
        }
        qw.lambda().orderByAsc(AdminRole::getAdmin);
        qw.lambda().orderBy(true, req.getOrder().equals("asc"), AdminRole::getCreateDate);
        return adminRoleMapper.selectPage(iPage, qw);
    }

    /**
     * 查询角色详情
     *
     * @param roleId
     * @return
     */
    @Override
    public AdminRole queryAdminRoleDetail(Integer roleId) {
        AdminRole ar = adminRoleMapper.selectById(roleId);
        List<Integer> menuIds = roleToMenuMapper.getRoleMenuIdsByRoleId(roleId);
        ar.setMenuIds(menuIds);
        return ar;
    }

    /**
     * 修改角色菜单权限
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRolePower(AdminRole ar) {
        QueryWrapper<RoleToMenu> qw = new QueryWrapper<>();
        qw.lambda().eq(RoleToMenu::getRoleId, ar.getId());
        RoleToMenu rtm = new RoleToMenu();
        rtm.setStatus(-1);
        roleToMenuMapper.update(rtm, qw);
        if (ar.getMenuIds() == null || ar.getMenuIds().size() == 0) {
            return true;
        }
        int num;
        int nums = 0;
        rtm = new RoleToMenu();
        rtm.setStatus(1);
        for (Integer item : ar.getMenuIds()) {
            qw.clear();
            qw.lambda().eq(RoleToMenu::getRoleId, ar.getId());
            qw.lambda().eq(RoleToMenu::getMenuId, item);
            num = roleToMenuMapper.update(rtm, qw);
            if (num < 1) {
                rtm = new RoleToMenu();
                rtm.setRoleId(ar.getId());
                rtm.setMenuId(item);
                rtm.setStatus(1);
                num = roleToMenuMapper.insert(rtm);
                if (num < 1) {
                    throw new ZekeException(400, "角色权限修改失败!");
                }
                rtm = new RoleToMenu();
                rtm.setStatus(1);
            }
            nums += num;
        }
        return nums == ar.getMenuIds().size();
    }

    /**
     * 查询角色是否是超管
     *
     * @param userId
     * @param flag
     * @return
     */
    @Override
    public Integer queryRoleIsAdmin(Integer userId, Integer flag) {
        Integer admin = adminRoleMapper.getRoleIsAdmin(userId, flag);
        return admin == null ? 0 : admin;
    }


    /**
     * 查询角色是否是超管
     *
     * @param roleId
     * @return
     */
    @Override
    public Integer queryRoleIsAdmin(Integer roleId) {
        QueryWrapper<AdminRole> qw = new QueryWrapper<>();
        qw.lambda().eq(AdminRole::getId, roleId);
        qw.lambda().eq(AdminRole::getStatus, 1);
        qw.lambda().select(AdminRole::getAdmin);
        AdminRole adminRole = adminRoleMapper.selectOne(qw);
        return adminRole == null ? 0 : adminRole.getAdmin();
    }

    /**
     * @param type:
     * @return Integer
     * @description 查询超管的角色id
     * @author czg
     * @date 2023/4/26 19:59
     */
    @Override
    public Integer queryAdminRoleId(Integer type) {
        Integer roleId = adminRoleMapper.getAdminRoleId(type);
        return roleId;
    }

    /**
     * 绑定角色
     *
     * @param userId
     * @param roleId
     */
    @Override
    public void bindUserRole(Integer userId, Integer roleId, Integer type) {
        QueryWrapper<UserToRole> qw = new QueryWrapper<>();
        qw.lambda().eq(UserToRole::getUserId, userId);
        if (LoginInfo.UserType.ADMIN == type) {
            qw.lambda().eq(UserToRole::getUserType, LoginInfo.UserType.ADMIN);
        } else if (LoginInfo.UserType.PHAR == type) {
            qw.lambda().eq(UserToRole::getUserType, LoginInfo.UserType.PHAR);
        }
        UserToRole ur = userToRoleMapper.selectOne(qw);
        if (ur == null) {
            ur = new UserToRole();
            ur.setUserId(userId);
            if (LoginInfo.UserType.ADMIN == type) {
                ur.setUserType(LoginInfo.UserType.ADMIN);
            } else if (LoginInfo.UserType.PHAR == type) {
                ur.setUserType(LoginInfo.UserType.PHAR);
            }
        }
        ur.setRoleId(roleId);
        ur.setStatus(1);
        if (ur.getId() == null) {
            userToRoleMapper.insert(ur);
        } else {
            userToRoleMapper.updateById(ur);
        }
    }

    /**
     * 获取用户的数据权限
     *
     * @return
     */
    @Override
    public List<String> getDataRoleByUser() {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        Integer admin = queryRoleIsAdmin(loginInfo.getId(), loginInfo.getType());
        return userToRoleMapper.getUserDataRole(loginInfo.getId(), admin);
    }
}
